#!/usr/bin/env python
#-*- coding: utf-8 -*-
#
# BSD License
# Copyright (c) 2011, Wang Qiang
# All rights reserved.

"""
Web Reader
Retrieval webs according to web configue file.
"""

from twisted.web.client import getPage
from twisted.internet import defer
from JQSelector.JQSelector import JQSelect, JQSelectPQ
from pyquery import PyQuery
from SuccessFlow import SuccessFlowFactory
from ErrorFlow import ErrorProcessor


class WebReader(object):
    """
    WebReader
    """
    def __init__(self, config, organize):
        """
        Constructor
        @param config: web configue file.
        """
        super(WebReader, self).__init__()
        self.config = config
        self.organize = organize

    def decodeConfig(self):
        """
        Decode the configue file.
        """
        try:
            organizeFile = open(self.organize, 'r').read()
        except:
            log.err()
            return
        mainlink = JQSelectPQ(organizeFile, 'a')[0]
        self.name = mainlink.attr('name')
        self.link = mainlink.attr('href')
        self.format = JQSelectPQ(organizeFile, 'format')[0].text()
        notationEl = JQSelectPQ(organizeFile, 'notation')
        self.notation = []
        for el in notationEl:
            num = el.attr('num')
            sel = el.text()
            self.notation.append((num, sel))

    def openLink(self):
        """
        Open the main link with twisted getPage
        @return d: deferred for getPage
        """
        self.decodeConfig()
        d = getPage(self.link)
        d.addCallbacks(self.processMainLink, self.errorMainLink)
        d.addErrback(self.errorParseMainLink)
        return d

    def processMainLink(self, html):
        """
        Process the html read from the main link.
        @param html: main link html.
        """
        alist = []
        for num, sel in self.notation:
            if not num:
                num = 20
            num = int(num)
            res = JQSelect(html, sel)
            resNum = (len(res) > num) and num or len(res)
            alist += res[0:resNum]
        return self.processAList(alist)

    def processAList(self, alist):
        """
        Process alist returned from the main link in deferred list.
        @param alist: list of <a> returned from main link.
        """
        # Construct deferred list
        dlist = []
        for a in alist:
            pqA = PyQuery(a)
            link = pqA.attr('href')
            d = getPage(link)
            sfactory = SuccessFlowFactory(self.config)
            processor = sfactory.getSucessFlow(self.format)
            errorProcessor = ErrorProcessor(self.organize)
            d.addCallbacks(processor.processHtml, errorProcessor.getPageError)
            d.addErrback(errorProcessor.parsePageError)
            dlist.append(d)
        return defer.DeferredList(dlist)

    def errorMainLink(self, error):
        """
        Process error in reading main link.
        @param error: the reading error.
        """
        log.err("Error in open MainLink:" + \
                self.organize + ":" + str(error))

    def errorParseMainLink(self, error):
        """
        @param error: parse error
        """
        log.err("Error in parse MainLink html:" + \
                self.organize + ":" + str(error))
